package com.sdk.scan.utils

import android.annotation.SuppressLint
import android.app.Activity
import android.app.PendingIntent
import android.content.Intent
import android.content.IntentFilter
import android.nfc.NfcAdapter
import android.nfc.Tag
import android.nfc.tech.NfcA
import android.os.Build
//import cn.flutter.plugin.aio.utils.LoggerUtils
import cn.oi.klittle.era.exception.KCatchException
import cn.oi.klittle.era.utils.KIntentUtils
import cn.oi.klittle.era.utils.KLoggerUtils.e
import java.util.Locale

class KNfcUtils {
    companion object {
        var TECHLISTS: Array<Array<String>>? = null; //NFC技术列表
        var FILTERS: Array<IntentFilter>? = null; //过滤器
    }

    var _onNfcResultCallBack: ((cardNo: String) -> Unit)? = null;

    ///fixme 刷卡结果回调
    fun onNfcResultCallBack(onNfcResultCallBack: ((cardNo: String) -> Unit)?) {
        _onNfcResultCallBack = onNfcResultCallBack;
    }

    ///处理nfc读取结果回调;cardNo 卡号
    private fun onNfcResult(cardNo: String?) {
        _onNfcResultCallBack?.let {
            if (cardNo != null && cardNo.length > 0) {
                it(cardNo);
            }
        }
    }

    var _onNfcNotEnabledCallBack: (() -> Unit)? = null;

    ///设备支持NFC功能，但是NFC功能没有开启时调用。在onResume()里调用，每次重新进入界面都会刷新。
    fun onNfcNotEnabledCallBack(onNfcNotEnabledCallBack: (() -> Unit)?) {
        _onNfcNotEnabledCallBack = onNfcNotEnabledCallBack;
    }

    private fun onNfcNotEnabled() {
        _onNfcNotEnabledCallBack?.let {
            it();
        }
    }

    var _onNfcNotSupportCallBack: (() -> Unit)? = null;

    ///设备不支持NFC刷卡功能时调用,在onStart()里调用，只调用一次。
    //fixme 设备支持NFC,但是开机启动时，NFC服务还没有开启导致的。从而异常。导致判断失误。这时需要重启NFC刷卡功能即可。
    fun onNfcNotSupportCallBack(onNfcNotSupportCallBack: (() -> Unit)?) {
        _onNfcNotSupportCallBack = onNfcNotSupportCallBack;
    }

    private fun onNfcNotSupport() {
        _onNfcNotSupportCallBack?.let {
            it();
        }
    }

    ///=============================================================================================
    var mNfcAdapter: NfcAdapter? = null;
    var pendingIntent: PendingIntent? = null;

    ///fixme Activity 生命周期调用的方法。
    fun onNewIntent(intent: Intent) {
        //KLoggerUtils.INSTANCE.e("========================onNewIntent:\t"+intent+"\t"+isEnableNFC());
        //fixme 版本升级之后，小米手机读出来的：Intent { flg=0x30000000 cmp=cn.nbjianghua.bwg.app.test/com.example.myapplication.MainActivity5 }
        //fixme PDA读出来的：{ act=android.nfc.action.TECH_DISCOVERED flg=0x30000000 cmp=cn.nbjianghua.bwg.app.test/com.example.myapplication.MainActivity5 (has extras) }	true
        if (isEnableNfc) {
            readFromNfc(intent)
        }
    }

    fun onResume(act: Activity) {
        try {
            try {
                //fixme 之前放在onCreate()里，会发生异常：java.lang.IllegalStateException: Foreground dispatch can only be enabled when your activity is resumed
                //fixme 所以放在onResume()里。比较好。
                if (isEnableNfc && mNfcAdapter == null) {
                    initNfc(act)
                    if (isNfcSupport) {
                        enableNfc(act)
                    }
                }
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
                e("NFC初始化异常(onResume())：\t" + KCatchException.getExceptionMsg(e), true)
            }
            if (isEnableNfc) {
                initNfc(act) //fixme 防止未初始化异常，未完成。再初始化一次。
            }
            if (isEnableNfc && isNfcSupport) {
                enableNfc(act)
                if (!isNfcEnabled()) {
                    //NFC功能没有开启回调
                    //fixme 关很快的，就是开需要点时间。
                    object : Thread() {
                        override fun run() {
                            super.run()
                            try {
                                //NFC开启和关闭需要时间不是实时的，所以延迟一下,单位毫秒。
                                //测试发现，大概需要2秒的时候（太慢了，等待2秒不太好）。关很快的，就是开需要点时间。
                                // 这里就等待200毫秒，太长了不好。（只有用户点击开关按钮之后不是马上返回，基本都没问题）
                                sleep(200)
                                act.runOnUiThread(Runnable {
                                    try {
                                        if (!isNfcEnabled()) {
                                            onNfcNotEnabled() //fixme NFC功能没有开启
                                        }
                                    } catch (e: java.lang.Exception) {
                                        e.printStackTrace()
                                    }
                                })
                            } catch (e: java.lang.Exception) {
                                e.printStackTrace()
                            }
                        }
                    }.start()
                }
            } else {
                try {
                    if (!isNfcSupport) {
                        if (isEnableNfc) {
                            onNfcNotSupport() //fixme 设备不支持NFC读卡功能(或者NFC刷卡失败。)
                        }
                    }
                } catch (e: java.lang.Exception) {
                    e.printStackTrace()
                }
            }
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
    }

    fun onPause(act: Activity) {
        if (isEnableNfc) {
            disableNfc(act)
        }
    }

    fun finish() {
        mNfcAdapter = null
        pendingIntent = null
    }
    ///=============================================================================================

    //fixme android 12(SDK 31),必须使用这个NFC才能正常读取。
    //fixme 由于更高的版本，如android 13（sdk 33）,又将这个移除了，所以我们自己建了一个一模一样的。
    val FLAG_MUTABLE: Int = 1 shl 25

    ///fixme 兼容android 12 获取PendingIntent
    @SuppressLint("WrongConstant")
    fun getNfcPendingIntennt(act: Activity): PendingIntent {
        if (pendingIntent == null) {
            if (Build.VERSION.SDK_INT >= 31) {
                //31 是android 12的版本。
                val intent: Intent =
                    Intent(act, act.javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
                //pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
                //pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
                //pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
                //pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                //fixme 必须指明这个FLAG_MUTABLE；才能正常读取标签。亲测可以；android 12及以上版本，必须指明，不然报错。
                //fixme PendingIntent.FLAG_IMMUTABLE 刷卡又反应，但是标签读取返回的是 null; 所以还是要使用 FLAG_MUTABLE
                pendingIntent = PendingIntent.getActivity(act, 0, intent, FLAG_MUTABLE)
            } else {
                //pendingIntent = PendingIntent.getActivity(
                //    act, 0, Intent(
                //        act, act.javaClass
                //    ).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0
                //)
                pendingIntent = PendingIntent.getActivity(
                    act, 0, Intent(
                        act, act.javaClass
                    ).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), FLAG_MUTABLE
                )
            }
        }
        return pendingIntent!!
    }

    //初始化nfc配置
    private fun initNfc(act: Activity) {
        if (isEnableRFID) {
            //fixme 如果开了RFID扫描；NFC就不开。
            return
        }
        if (mNfcAdapter == null) {
            try {
                if (mNfcAdapter == null) {
                    mNfcAdapter = NfcAdapter.getDefaultAdapter(act)
                    lastClickTime_nfc = 0 //fixme 防止第一次进入，刷卡无效。
                }
                if (mNfcAdapter == null) {
                    //设备不支持NFC读取
                    isNfcSupport = false
                } else if (!mNfcAdapter!!.isEnabled) {
                    //请在系统设置中先启用NFC功能！
                } else if (pendingIntent == null) {
                    try {
                        pendingIntent = getNfcPendingIntennt(act)
                        //pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
                        if (act.getIntent() != null) {
                            onNewIntent(act.getIntent())
                        }
                    } catch (e: java.lang.Exception) {
                        e(
                            "异常1：\tmNfcAdapter:\t$mNfcAdapter\tisNfcSupport:\t$isNfcSupport\tpendingIntent:\t$pendingIntent",
                            true
                        )
                        e(
                            "KNfcActivity NFC pendingIntent异常1：\t" + KCatchException.getExceptionMsg(
                                e
                            ), true
                        )
                        isNfcSupport = false
                        mNfcAdapter = null
                        reInitNfc(act)
                    }
                }
            } catch (e: java.lang.Exception) {
                //fixme 如果设备支持NFC,这种异常，一般都是开机启动时，NFC服务还没有开启导致的。
                e(
                    "异常2：\tmNfcAdapter:\t$mNfcAdapter\tisNfcSupport:\t$isNfcSupport\tpendingIntent:\t$pendingIntent",
                    true
                )
                e("KNfcActivity NFC初始化异常2：\t" + KCatchException.getExceptionMsg(e), true)
                isNfcSupport = false
                mNfcAdapter = null
                reInitNfc(act)
            }
        }
    }

    //重新初始化nfc配置
    private fun reInitNfc(act: Activity) {
        //fixme 再初始化一次。
        if (mNfcAdapter == null && isEnableNfc) {
            try {
                if (mNfcAdapter == null) {
                    mNfcAdapter = NfcAdapter.getDefaultAdapter(act)
                }
                if (mNfcAdapter == null) {
                    //设备不支持NFC读取
                    isNfcSupport = false
                } else if (!mNfcAdapter!!.isEnabled) {
                    //请在系统设置中先启用NFC功能！
                } else if (pendingIntent == null) {
                    pendingIntent = getNfcPendingIntennt(act)
                    //pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
                    if (act.getIntent() != null) {
                        onNewIntent(act.getIntent())
                    }
                }
            } catch (e2: java.lang.Exception) {
                //fixme 如果设备支持NFC,这种异常，一般都是开机启动时，NFC服务还没有开启导致的。
                e(
                    "异常3:\tmNfcAdapter:\t$mNfcAdapter\tisNfcSupport:\t$isNfcSupport\tpendingIntent:\t$pendingIntent",
                    true
                )
                e("KNfcActivity NFC初始化异常3：\t" + KCatchException.getExceptionMsg(e2), true)
                isNfcSupport = false
                mNfcAdapter = null
            }
        }
    }

    /**
     * 关闭nfc读卡功能【nfc实际功能没有关闭，只是当前页不再监听nfc读卡】
     */
    fun disableNfc(act: Activity) {
        if (isEnableRFID) {
            //fixme 如果开了RFID扫描；NFC就不开。
            return
        }
        try {
            if (mNfcAdapter != null) {
                mNfcAdapter!!.disableForegroundDispatch(act) // 取消调度
            }
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            e("disableNfc()异常：\t" + KCatchException.getExceptionMsg(e), true)
        }
    }

    /**
     * 跳转NFC设置界面
     */
    fun goNFCSetting(act: Activity) {
        KIntentUtils.goNFCSetting(act)
    }

    //fixme 是否开启了RFID功能；默认不开启，如果开启了，NFC就不会开启了。优先级比NFC高；RFID和NFC不可兼容。即硬件目前只支持其中一种；不能同时支持。
    //默认不开启
    var isEnableRFID = false;

    ///是否开启Nfc功能
    var isEnableNfc = true;

    ///判断是否支持Nfc刷卡功能
    var isNfcSupport = true;

    ///控制nfc读取回调开关。
    var isEnableNfcRead = true;

    /**
     * 判断NFC功能是否开启
     */
    fun isNfcEnabled(): Boolean {
        if (isNfcSupport && mNfcAdapter != null) {
            return mNfcAdapter!!.isEnabled
        }
        return false
    }

    // 两次刷卡之间的点击间隔不能少于350毫秒（即0.35秒）
    var MIN_CLICK_DELAY_TIME_nfc: Long = 350
    var lastClickTime_nfc: Long = 0 //记录最后一次刷卡时间

    //判断是否快速刷卡
    fun isFastNfc(): Boolean {
        var flag = false
        val curClickTime = System.currentTimeMillis()
        if ((curClickTime - lastClickTime_nfc) <= MIN_CLICK_DELAY_TIME_nfc) {
            flag = true //快速点击
        }
        lastClickTime_nfc = curClickTime
        return flag
    }

    /**
     * 开启nfc读卡功能【当前页面继续监听nfc读卡功能】
     */
    fun enableNfc(act: Activity) {
        if (isEnableRFID) {
            //fixme 如果开了RFID扫描；NFC就不开。
            return
        }
        try {
            if (mNfcAdapter != null && mNfcAdapter!!.isEnabled) {
                if (pendingIntent == null) {
                    pendingIntent = getNfcPendingIntennt(act)
                    //pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
                }
                if (mNfcAdapter != null && pendingIntent != null) {
                    if (TECHLISTS == null || FILTERS == null) {
                        try {
                            TECHLISTS = arrayOf(
                                arrayOf(
                                    NfcA::class.java.name
                                )
                            )
                            FILTERS =
                                arrayOf(IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED, "*/*"))
                        } catch (ignored: java.lang.Exception) {
                        }
                    }
                    //enableForegroundDispatch================调度act:	class com.idogfooding.glassscanner.bwg2.MainActivity
                    e("enableForegroundDispatch================调度act:\t" + act.javaClass + "\t是否正在读卡：\t" + isReadFromNfc);
                    //fixme 这行代码是添加调度，效果是读标签的时候不会弹出候选程序，直接用本程序处理(当前Activity处理，就不会再弹系统询问框了。)
                    mNfcAdapter!!.enableForegroundDispatch(
                        act,
                        pendingIntent,
                        FILTERS,
                        TECHLISTS
                    )
                }
            }
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
            e(
                "mNfcAdapter:\t$mNfcAdapter\tisNfcSupport:\t$isNfcSupport\tpendingIntent:\t$pendingIntent",
                true
            )
            e("KNfcActivity NFC开启异常：\t" + KCatchException.getExceptionMsg(e), true)
        }
    }

    var isReadFromNfc = false;//判断是否正在读卡。

    //fixme NFC刷卡读取
    ///fixme 测试发现，在android原生页面能够监听NFC刷卡，并且也能拿到Tag对象。
    ///fixme 但是在Flutter页面，intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); 始终为空。参考地址：https://www.jianshu.com/p/06905cd49592;
    ///fixme 所以最终我们不使用这个NfcActivity；flutter页面我们直接改成使用 nfc_manager 插件。亲测有效。
    fun readFromNfc(intent: Intent?) {
        if (intent == null) {
            return
        }
        isReadFromNfc = true;
        //fixme 版本升级之后，小米手机读出来的：Intent { flg=0x30000000 cmp=cn.nbjianghua.bwg.app.test/com.example.myapplication.MainActivity5 }
        //fixme PDA读出来的：{ act=android.nfc.action.TECH_DISCOVERED flg=0x30000000 cmp=cn.nbjianghua.bwg.app.test/com.example.myapplication.MainActivity5 (has extras) }	true
        try {
            //KLoggerUtils.INSTANCE.e("NFC数据读取：intent:" + intent);
            var tag: Tag? = null;
            //if (android.os.Build.VERSION.SDK_INT >= 33) {
            //    tag == intent.getParcelableExtra(NfcAdapter.EXTRA_TAG, Tag::class.java);
            //} else {
            //    tag == intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            //}
            tag == intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            //act:	class com.idogfooding.glassscanner.bwg2.MainActivity
            //LoggerUtils.e("刷卡结果================onNewIntent：\t" + intent);
            //Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x30000000 cmp=com.idogfooding.glassscanner/.bwg2.MainActivity (has extras) }
            //tag：	null	SDK_INT:28
            //LoggerUtils.e("刷卡读取结果================tag：\t" + tag + "\tSDK_INT:" + android.os.Build.VERSION.SDK_INT);
            //KLoggerUtils.INSTANCE.e("NFC数据读取：tag:" + tag);
            //fixme PDA: NFC数据读取：tag:TAG: Tech [android.nfc.tech.NfcA, android.nfc.tech.MifareClassic, android.nfc.tech.NdefFormatable]
            //fixme 小米手机：NFC数据读取：tag:null
            //NFC数据读取：intent:Intent { act=android.nfc.action.TECH_DISCOVERED flg=0x30000000 cmp=cn.nbjianghua.bwg.app.test/com.example.myapplication.MainActivity5 (has extras) }
            //NFC数据读取：tag:TAG: Tech [android.nfc.tech.NfcA, android.nfc.tech.MifareClassic, android.nfc.tech.NdefFormatable]
            if (null != tag) {
                //获取 Tag 读取 ID 得到字节数组 转字符串 转码 得到卡号（默认16进制 这请自便）
                //Long cardNo = Long.parseLong(ByteArrayTohexHepler.flipHexStr(ByteArrayToHexString(tag.getId())), 16);
                //KLoggerUtils.INSTANCE.e("卡号：\t"+cardNo.toString());
                val tagId = tag.id
                // 15AF503D
                val str = bytesToHexString(tagId)
                //KLoggerUtils.INSTANCE.e("STR:\t"+str);
                // 363810877
                val nfcCardNo = hexToDecString(str)
                //KLoggerUtils.INSTANCE.e("nfcCardNo:\t"+nfcCardNo,true);
                //回调
                if (nfcCardNo != null && nfcCardNo.trim { it <= ' ' }.length > 0) {
                    if (isEnableNfcRead) {
                        if (isFastNfc()) {
                            return  //fixme 防止快速刷卡
                        }
                        onNfcResult(nfcCardNo)
                    }
                } else {
                    e("NFC刷卡为空,nfcCardNo:\t$nfcCardNo", true)
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
            e("NFC刷卡异常：\t" + KCatchException.getExceptionMsg(e), true)
        }
        isReadFromNfc = false;
    }

    //原厂的
    private fun bytesToHexString(bArray: ByteArray): String {
        val sb = StringBuilder(bArray.size)
        var sTemp: String
        for (i in bArray.indices) {
            sTemp = Integer.toHexString(0xFF and bArray[i].toInt())
            if (sTemp.length < 2) sb.append(0)
            sb.append(sTemp.uppercase(Locale.getDefault()))
        }
        return sb.toString()
    }

    //原厂的
    private fun hexToDecString(hex: String): String {
        try {
            val before = hex.toLong(16).toInt() //大于Integer.MAX_VALUE时出现截断，估计就不对了
            val r24 = before shr 24 and 0x000000FF
            val r8 = before shr 8 and 0x0000FF00
            val l8 = before shl 8 and 0x00FF0000
            val l24 = before shl 24 and -0x1000000
            //fixme Long类型；会去除前面的0；如：0758694741 会变成 758694741
            //fixme 所以，如果首字符是0；本来是十位，读取的时候就是九位了；位数就发生变化了。（目前没办法知道前面是否带0，且带了几个0）
            return Integer.toHexString((r24 or r8 or l8 or l24)).toLong(16).toString()
        } catch (e: Exception) {
            e.printStackTrace()
            e("KNfcActivity NFC读卡异常：\t" + e.message, true)
        }
        return ""
    }

    //和bytesToHexString效果是一样的。
    private fun ByteArrayToHexString(inarray: ByteArray): String {
        var i: Int
        var _in: Int
        val hex =
            arrayOf("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
        var out = ""
        var j = 0
        while (j < inarray.size) {
            _in = inarray[j].toInt() and 0xff
            i = (_in shr 4) and 0x0f
            out += hex[i]
            i = _in and 0x0f
            out += hex[i]
            ++j
        }
        return out
    }
}